package com.qingcheng.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.qingcheng.dao.BrandMapper;
import com.qingcheng.dao.SpecMapper;
import com.qingcheng.service.goods.SkuSearchService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 岳剑飞
 * @Company http://www.ithiema.com
 */
@Service
public class SkuSearchServiceImpl implements SkuSearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private BrandMapper brandMapper;

    @Autowired
    private SpecMapper specMapper;

    /**
     * 关键字逻辑搜索
     *
     * @param searchMap
     * @return
     */
    @Override
    public Map searchMap(Map<String, String> searchMap) {

        //1. 封装查询条件
        SearchRequest searchRequest = new SearchRequest("sku");  //创建查询请求对象
        searchRequest.types("doc");  //设置查询的类型

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();  //查询源构建器
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//布尔查询构建器
        //1.1 关键字搜索
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", searchMap.get("keywords"));
        boolQueryBuilder.must(matchQueryBuilder);

        //1.2 商品分类过滤
        if (searchMap.get("category") != null) {//查询条件中是否含有商品分类
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("categoryName", searchMap.get("category"));
            boolQueryBuilder.filter(termQueryBuilder);
        }
        //1.3 品牌过滤
        if (searchMap.get("brand") != null) {//查询条件中是否含有品牌信息
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brandName", searchMap.get("brand"));
            boolQueryBuilder.filter(termQueryBuilder);
        }
        //1.4 规格过滤
        for (String key : searchMap.keySet()) {
            if (key.startsWith("spec.")){ //如果是规格参数
                TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key+".keyword", searchMap.get(key));
                boolQueryBuilder.filter(termQueryBuilder);
            }
        }

        //1.5 价格过滤
        if (searchMap.get("price")!=null){
            //存在价格筛选条件
            String[] prices = searchMap.get("price").split("-");
            if (!prices[0].equals("0")){   //最低价格不等于 0
                RangeQueryBuilder rangeQueryBuilder=QueryBuilders.rangeQuery("price").gte(prices[0]+"00");
                boolQueryBuilder.filter(rangeQueryBuilder);

            }
            if (!prices[1].equals("*")){   //最高价格有上限
                RangeQueryBuilder rangeQueryBuilder=QueryBuilders.rangeQuery("price").lte(prices[1]+"00");
                boolQueryBuilder.filter(rangeQueryBuilder);

            }
        }

        searchSourceBuilder.query(boolQueryBuilder);

        //1.7 分页查询
        Integer pageNo=Integer.parseInt(searchMap.get("pageNo"));  //页码
        Integer pageSize=30;    //页大小
        //起始记录下标
        int fromIndex=(pageNo-1)*pageSize;
        searchSourceBuilder.from(fromIndex);  //开始索引
        searchSourceBuilder.size(pageSize);     //页大小


        //1.6 聚合查询(商品分类)
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("sku_category").field("categoryName");
        searchSourceBuilder.aggregation(termsAggregationBuilder);

        //1.7 排序
        String sort = searchMap.get("sort");  //排序规则  升序
        String sortOrder = searchMap.get("sortOrder");  //排序规则, 降序
        if (!"".equals(sort)){
            searchSourceBuilder.sort(sort, SortOrder.valueOf(sortOrder));
        }

        //1.8 设置高亮显示
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("name").preTags("<font style='color:red'>").postTags("</font>");
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);

        //2. 封装查询结果
        Map resultMap = new HashMap();
        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits searchHits = searchResponse.getHits();
            long totalHits = searchHits.getTotalHits();
            System.out.println("记录数: " + totalHits);
            SearchHit[] hits = searchHits.getHits();

            //2.1 商品列表
            List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
            for (SearchHit hit : hits) {
                Map<String, Object> skuMap = hit.getSourceAsMap();
                //提取高亮内容
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                HighlightField highlightFieldName = highlightFields.get("name");
                Text[] fragments = highlightFieldName.fragments();
                skuMap.put("name",fragments[0].toString());  //使用高亮的内容替换原来的内容

                resultList.add(skuMap);
            }
            resultMap.put("rows", resultList);

            //2.2 商品分类列表
            Aggregations aggregations = searchResponse.getAggregations();
            Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
            Terms terms = (Terms) aggregationMap.get("sku_category");
            List<? extends Terms.Bucket> buckets = terms.getBuckets();
            List<String> categoryList = new ArrayList<>();
            for (Terms.Bucket bucket : buckets) {
                categoryList.add(bucket.getKeyAsString());
            }
            resultMap.put("categoryList", categoryList);

            //2.3 品牌列表
            String categoryName = "";  //商品分类名称
            if (searchMap.get("category") == null) { //如果没有分类条件
                if (categoryList.size() > 0) {
                    categoryName = categoryList.get(0);  // 提取分类列表的第一个列表
                }
            } else {
                categoryName = searchMap.get("category");
            }
            //查询品牌列表
            if (searchMap.get("brand") == null) {
                // 当查询条件中包含品牌信息.则不查询品牌列表
                List<Map> brandList = brandMapper.findListByCategoryName(categoryName);
                //封装
                resultMap.put("brandList", brandList);
            }

            //2.4 规格列表
            List<Map> specList = specMapper.findListByCategoryName(categoryName);  // 规格列表
            for (Map spec : specList) {
                String[] options = ((String) spec.get("options")).split(","); //规格选项列表
                spec.put("options", options);

            }
            resultMap.put("specList",specList);

            //2.5 计算总页数
            long totalCount=searchHits.getTotalHits();  //总记录数
            long pageCount=(totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1); //总页数
            resultMap.put("totalPages",pageCount);

        } catch (
                IOException e) {
            e.printStackTrace();
        }
        return resultMap;
    }
}
